package com.xiashitech.agent.utils;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.xiashitech.agent.cache.status.CacheStatus;
import com.xiashitech.agent.cache.system.CacheEnv;
import com.xiashitech.agent.config.StartConfig;
import com.xiashitech.agent.grpc.XsAgentStatusClient;
import com.xiashitech.agent.proxy.hutool.StrUtil;
import com.xiashitech.interfaces.agent.constants.AgentStatus;
import com.xiashitech.agent.constants.ErrorCode;
import com.xiashitech.agent.instrumentation.log.XSLevel;
import com.xiashitech.interfaces.agent.dto.SystemInfoDTO;
import com.xiashitech.interfaces.apiservice.dto.system.SystemInfoRequest;
import com.xiashitech.interfaces.apiservice.dto.system.SystemInfoResponse;
import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;

public class CacheUtil {
    private static final Logger logger = Logger.getLogger(CacheUtil.class.getName());
    /**
     * 同步agent状态到agentService，只会在 agent 随应用在启动时执行一次，后续应用执行期间不会再次执行
     * @param agentStatus
     */
    public static void syncAgentStatus(AgentStatus agentStatus) {
        if(agentStatus == null) {
            return;
        }
        try {
            /**
             * 同步agent启动状态
             */
            String param = JsonUtil.convertObjectToString(SystemInfoRequest.builder().id(StartConfig.getParamValueFromKey(StartConfig.systemId)).microServiceId(InstrumentationConfig.get().getString("otel.service.name")).agentStatus(agentStatus.getValue()).build());
            System.out.println("###CacheUtil service"+StartConfig.getParamValueFromKey(StartConfig.agentService));
            System.out.println("###CacheUtil param"+ param);
            String response = null;
            if(XiashiGrpcUtil.useGrpc()) {
                response = XsAgentStatusClient.getClient().createAgentStatus(param);
            } else {
                //response = HttpUtil.doPost(StartConfig.getParamValueFromKey(StartConfig.agentService) + StartConfig.serverContextPath + "/v1/agent/syncAgentStatus", param, "application/json;charset=UTF-8");
                response = HttpUtil.doPost(StartConfig.getAgentServiceRoot() + "/v1/agent/syncAgentStatus", param, "application/json;charset=UTF-8");
            }
            System.out.println("###CacheUtil response"+ response);
            if(response != null && !response.isEmpty() && JsonUtil.isJson(response)) {
                SystemInfoResponse systemInfoResponse = JsonUtil.convertStringToObject(response, SystemInfoResponse.class);
                if(systemInfoResponse != null && ErrorCode.RESULT_1001.getCode().equals(systemInfoResponse.getCode())) {
                    if(Boolean.valueOf(System.getProperty("xs.debug")).booleanValue()) {
                        logger.log(XSLevel.DEBUG, "The agent status is synchronized successfully!");
                    }
                    CacheStatus.setAgentStatus(agentStatus);
                } else {
                    if(Boolean.valueOf(System.getProperty("xs.debug")).booleanValue()) {
                        logger.log(XSLevel.DEBUG, "The agent status is not updated!");
                    }
                }
            } else {
                if(Boolean.valueOf(System.getProperty("xs.debug")).booleanValue()) {
                    logger.log(XSLevel.DEBUG, "The agent status synchronization fails 1! ");
                }
            }
        } catch (Throwable e) {
            logger.log(XSLevel.DEBUG, "The agent fails to synchronize the start status to the agentservice because the agentservice Service is unavailable.");
        }
    }

    /**
     * 在用户在访问业务系统过程中，可能会调用这方法，且可能会多次调用，但一次成功后，即不会再调用，次数应该不会很多
     * @param host
     */
    public static void syncAgentHost(String host) {
        {
            if(host == null) {
                return;
            }
        }
        new Thread(()-> {
            try {
                /**
                 * 同步agent HOST
                 */
                String param = JsonUtil.convertObjectToString(SystemInfoRequest.builder().id(StartConfig.getParamValueFromKey(StartConfig.systemId)).microServiceId(InstrumentationConfig.get().getString("otel.service.name")).host(host).build());

                String response = null;
                if(XiashiGrpcUtil.useGrpc()) {
                    response = XsAgentStatusClient.getClient().createAgentHost(param);
                } else {
                    // response = HttpUtil.doPost(StartConfig.getParamValueFromKey(StartConfig.agentService) + StartConfig.serverContextPath + "/v1/agent/syncAgentHost", param, "application/json;charset=UTF-8");
                    response = HttpUtil.doPost(StartConfig.getAgentServiceRoot() + "/v1/agent/syncAgentHost", param, "application/json;charset=UTF-8");
                }
                System.out.println("###CacheUtil apiService "+StartConfig.getParamValueFromKey(StartConfig.agentService));
                System.out.println("###CacheUtil syncAgentHost params:"+param+"response:"+response);
                if (response != null && !response.isEmpty() && JsonUtil.isJson(response)) {
                    SystemInfoResponse systemInfoResponse = JsonUtil.convertStringToObject(response, SystemInfoResponse.class);
                    if (systemInfoResponse != null && ErrorCode.RESULT_1001.getCode().equals(systemInfoResponse.getCode())) {
                        if (Boolean.valueOf(System.getProperty("xs.debug")).booleanValue()) {
                            logger.log(XSLevel.DEBUG, "The agent host is synchronized successfully!");
                        }
                        CacheEnv.setHost(host);
                    } else {
                        if (Boolean.valueOf(System.getProperty("xs.debug")).booleanValue()) {
                            logger.log(XSLevel.DEBUG, "The agent host is not updated!");
                        }
                    }
                } else {
                    if (Boolean.valueOf(System.getProperty("xs.debug")).booleanValue()) {
                        logger.log(XSLevel.DEBUG, "The agent host synchronization fails!");
                    }
                }
            } catch (Throwable e) {
                logger.log(XSLevel.DEBUG, "The agent fails to synchronize the start status to the agentservice because the agentservice Service is unavailable.");
            }
        }).start();
    }
    /**
     * 查询agentService更新CacheStatus
     */
    public static void updateCacheStatus() {
        try {
            Map<String,String> params = new HashMap();
            params.put("systemId",StartConfig.getParamValueFromKey(StartConfig.systemId));
            params.put("microServiceId",InstrumentationConfig.get().getString("otel.service.name"));
            if(XiashiGrpcUtil.useGrpc()) {
                // System.out.println( Thread.currentThread().getId() + " T" + System.nanoTime() + "..... updateCacheStatus ..... start .....");
                XsAgentStatusClient.getClient().agentStatus(params);
                // System.out.println( Thread.currentThread().getId() + " T" + System.nanoTime() + "..... updateCacheStatus ..... end .....:");
            } else {
                // String response = HttpUtil.doGet(StartConfig.getParamValueFromKey(StartConfig.agentService)+StartConfig.serverContextPath + "/v1/agent/agentStatus",params);
                String response = HttpUtil.doGet(StartConfig.getAgentServiceRoot() + "/v1/agent/agentStatus",params);
                if(response != null && !response.isEmpty()  && JsonUtil.isJson(response)) {
                    SystemInfoResponse systemInfoResponse = JsonUtil.convertStringToObject(response, SystemInfoResponse.class);
                    if (systemInfoResponse != null && ErrorCode.RESULT_1001.getCode().equals(systemInfoResponse.getCode())) {
                        List<SystemInfoDTO> systemInfos = systemInfoResponse.getSystemInfos();
                        if(systemInfos != null) {
                            CacheStatus.setCacheStatusByValue(systemInfos.get(0).getAgentStatus());
                        }
                    }
                }
            }
        } catch (Throwable e) {
            if(Boolean.valueOf(System.getProperty("xs.debug")).booleanValue()) {
                logger.log(XSLevel.DEBUG, "The agent status synchronization fails 2!");
            }
        }
    }

    /**
     * agent发送心跳信号给agentService
     */
    public static void heartBeat() {
        try {
            Map<String,String> params = new HashMap();
            params.put("systemId",StartConfig.getParamValueFromKey(StartConfig.systemId));
            params.put("microServiceId",InstrumentationConfig.get().getString("otel.service.name"));
            // HttpUtil.doGet(StartConfig.getParamValueFromKey(StartConfig.agentService)+StartConfig.serverContextPath + "/v1/agent/heartBeat",params);
            HttpUtil.doGet(StartConfig.getAgentServiceRoot() + "/v1/agent/heartBeat",params);
        } catch (Throwable e) {
            if(Boolean.valueOf(System.getProperty("xs.debug")).booleanValue()) {
                logger.log(XSLevel.DEBUG, "The agent fails to send heartbeat signals!");
            }
        }
    }

    /**
     * 同步水印开关状态
     * @param dwmStatusUrl
     */
    public static void dwmStatusSync(String dwmStatusUrl) {
        String systemId = StartConfig.getParamValueFromKey(StartConfig.systemId);
        String url = StrUtil.format(dwmStatusUrl, systemId);
        String response = HttpUtil.doGet(url, null);
        XSUtil.debug(CacheUtil.class, "同步水印开关接口:[{}],响应:{}", url, response);
        if (JsonUtil.isJson(response)) {
            JSONObject jsonObject = JSONUtil.parseObj(response);
            if (jsonObject.getInt("status") == 0 && jsonObject.getJSONObject("data") != null) {
                CacheStatus.setDwmEnable(jsonObject.getByPath("data.switch_status", Boolean.class));
            }
        }
    }
}
